winsafe\user\handles/hwnd.rs
1#![allow(non_camel_case_types, non_snake_case)]
2
3use crate::co;
4use crate::decl::*;
5use crate::guard::*;
6use crate::kernel::privs::*;
7use crate::msg::*;
8use crate::prelude::*;
9use crate::user::{callbacks, ffi, privs::*};
10
11handle! { HWND;
12 /// Handle to a
13 /// [window](https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types#hwnd).
14}
15
16impl HWND {
17 /// Represents all top-level windows in
18 /// [`HWND::PostMessage`](crate::HWND::PostMessage) and
19 /// [`HWND::SendMessage`](crate::HWND::SendMessage).
20 pub const BROADCAST: HWND = HWND(0xffff as _);
21
22 /// Represents the desktop window in [`HWND::GetDC`](crate::HWND::GetDC).
23 pub const DESKTOP: HWND = HWND(std::ptr::null_mut());
24
25 /// Calls
26 /// [`HWND::GetWindowLongPtr`](crate::HWND::GetWindowLongPtr) to retrieve
27 /// the window [`HINSTANCE`](crate::HINSTANCE).
28 #[must_use]
29 pub fn hinstance(&self) -> HINSTANCE {
30 unsafe { HINSTANCE::from_ptr(self.GetWindowLongPtr(co::GWLP::HINSTANCE) as _) }
31 }
32
33 /// Calls
34 /// [`HWND::GetClassLongPtr`](crate::HWND::GetClassLongPtr) to retrieve the
35 /// [class atom](https://stackoverflow.com/a/64437627/6923555) and check
36 /// whether the window was created from a dialog resource.
37 #[must_use]
38 pub fn is_dialog(&self) -> bool {
39 self.GetClassLongPtr(co::GCLP::ATOM) as u16 == WC_DIALOG
40 }
41
42 /// Calls
43 /// [`HWND::SetWindowLongPtr`](crate::HWND::SetWindowLongPtr) to set the
44 /// window styles.
45 pub fn set_style(&self, style: impl Into<co::WS>) {
46 let style: co::WS = style.into();
47 unsafe {
48 self.SetWindowLongPtr(co::GWLP::STYLE, style.raw() as _);
49 }
50 }
51
52 /// Calls [`HWND::SetWindowLongPtr`](crate::HWND::SetWindowLongPtr) to set
53 /// the extended window styles.
54 pub fn set_style_ex(&self, ex_style: impl Into<co::WS_EX>) {
55 let ex_style: co::WS_EX = ex_style.into();
56 unsafe {
57 self.SetWindowLongPtr(co::GWLP::EXSTYLE, ex_style.raw() as _);
58 }
59 }
60
61 /// Calls [`HWND::GetWindowLongPtr`](crate::HWND::GetWindowLongPtr) to
62 /// retrieve the window styles.
63 #[must_use]
64 pub fn style(&self) -> co::WS {
65 unsafe { co::WS::from_raw(self.GetWindowLongPtr(co::GWLP::STYLE) as _) }
66 }
67
68 /// Calls [`HWND::GetWindowLongPtr`](crate::HWND::GetWindowLongPtr) to
69 /// retrieve the extended window styles.
70 #[must_use]
71 pub fn style_ex(&self) -> co::WS_EX {
72 unsafe { co::WS_EX::from_raw(self.GetWindowLongPtr(co::GWLP::EXSTYLE) as _) }
73 }
74
75 /// [`ArrangeIconicWindows`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-arrangeiconicwindows)
76 /// function.
77 pub fn ArrangeIconicWindows(&self) -> SysResult<u32> {
78 match unsafe { ffi::ArrangeIconicWindows(self.ptr()) } {
79 0 => Err(GetLastError()),
80 height => Ok(height),
81 }
82 }
83
84 /// [`BeginPaint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-beginpaint)
85 /// function.
86 ///
87 /// In the original C implementation, `BeginPaint` returns a handle which
88 /// must be passed to
89 /// [`EndPaint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-endpaint),
90 /// as a cleanup operation. Also, you must allocate and pass a
91 /// [`PAINTSTRUCT`](crate::PAINTSTRUCT) object.
92 ///
93 /// Here, the cleanup is performed automatically, because `BeginPaint`
94 /// returns an [`EndPaintGuard`](crate::guard::EndPaintGuard), which stores
95 /// the `PAINTSTRUCT` and automatically calls `EndPaint` when the guard goes
96 /// out of scope. You must, however, keep the guard alive, otherwise the
97 /// cleanup will be performed right away.
98 ///
99 /// # Examples
100 ///
101 /// ```no_run
102 /// use winsafe::{self as w, prelude::*};
103 ///
104 /// let hwnd: w::HWND; // initialized somewhere
105 /// # let hwnd = w::HWND::NULL;
106 ///
107 /// let hdc = hwnd.BeginPaint()?;
108 ///
109 /// // do your hdc painting...
110 ///
111 /// // EndPaint() called automatically
112 /// # w::SysResult::Ok(())
113 /// ```
114 ///
115 /// If you don't use the returned device context handle, you must still keep
116 /// the guard alive:
117 ///
118 /// ```no_run
119 /// use winsafe::{self as w, prelude::*};
120 ///
121 /// let hwnd: w::HWND; // initialized somewhere
122 /// # let hwnd = w::HWND::NULL;
123 ///
124 /// let _hdc = hwnd.BeginPaint()?; // keep guard alive
125 ///
126 /// // do your hdc painting...
127 ///
128 /// // EndPaint() called automatically
129 /// # w::SysResult::Ok(())
130 /// ```
131 #[must_use]
132 pub fn BeginPaint(&self) -> SysResult<EndPaintGuard<'_>> {
133 let mut ps = PAINTSTRUCT::default();
134 unsafe {
135 ptr_to_sysresult_handle(ffi::BeginPaint(self.ptr(), pvoid(&mut ps)))
136 .map(|h| EndPaintGuard::new(self, h, ps))
137 }
138 }
139
140 /// [`BringWindowToTop`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-bringwindowtotop)
141 /// function.
142 pub fn BringWindowToTop(&self) -> SysResult<()> {
143 bool_to_sysresult(unsafe { ffi::BringWindowToTop(self.ptr()) })
144 }
145
146 /// [`ChildWindowFromPoint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-childwindowfrompoint)
147 /// function.
148 #[must_use]
149 pub fn ChildWindowFromPoint(&self, pt: POINT) -> Option<HWND> {
150 ptr_to_option_handle(unsafe { ffi::ChildWindowFromPoint(self.ptr(), pt.x, pt.y) })
151 }
152
153 /// [`ClientToScreen`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-clienttoscreen)
154 /// function.
155 ///
156 /// If you need to convert a [`RECT`](crate::RECT), see the
157 /// [`HWND::ClientToScreenRc`](crate::HWND::ClientToScreenRc) function.
158 #[must_use]
159 pub fn ClientToScreen(&self, pt: POINT) -> SysResult<POINT> {
160 let mut buf = pt;
161 bool_to_sysresult(unsafe { ffi::ClientToScreen(self.ptr(), pvoid(&mut buf)) }).map(|_| buf)
162 }
163
164 /// [`ClientToScreen`](crate::HWND::ClientToScreen) method for a
165 /// [`RECT`](crate::RECT).
166 #[must_use]
167 pub fn ClientToScreenRc(&self, rc: RECT) -> SysResult<RECT> {
168 let mut buf = rc;
169 bool_to_sysresult(unsafe { ffi::ClientToScreen(self.ptr(), pvoid(&mut buf.left)) })?;
170 bool_to_sysresult(unsafe { ffi::ClientToScreen(self.ptr(), pvoid(&mut buf.right)) })
171 .map(|_| buf)
172 }
173
174 /// [`CloseWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-closewindow)
175 /// function.
176 ///
177 /// Note that this method will actually minimize the window, not destroy it.
178 pub fn CloseWindow(&self) -> SysResult<()> {
179 bool_to_sysresult(unsafe { ffi::CloseWindow(self.ptr()) })
180 }
181
182 /// [`CreateWindowEx`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw)
183 /// function.
184 ///
185 /// # Safety
186 ///
187 /// This method will create raw dynamic windows and controls outside the
188 /// library safety – it's up to you to handle all the messages. You must use
189 /// a properly registered class name and, if creating a custom window,
190 /// provide its own window procedure.
191 ///
192 /// The usable ID range for child controls is
193 /// [8 to 57,343](https://stackoverflow.com/a/18192766/6923555).
194 pub unsafe fn CreateWindowEx(
195 ex_style: co::WS_EX,
196 class_name: AtomStr,
197 title: Option<&str>,
198 style: co::WS,
199 pos: POINT,
200 size: SIZE,
201 hwnd_parent: Option<&HWND>,
202 hmenu: IdMenu,
203 hinstance: &HINSTANCE,
204 lparam: Option<isize>,
205 ) -> SysResult<HWND> {
206 ptr_to_sysresult_handle(unsafe {
207 ffi::CreateWindowExW(
208 ex_style.raw(),
209 class_name.as_ptr(),
210 WString::from_opt_str(title).as_ptr(),
211 style.raw(),
212 pos.x,
213 pos.y,
214 size.cx,
215 size.cy,
216 hwnd_parent.map_or(std::ptr::null_mut(), |h| h.ptr()),
217 hmenu.as_ptr(),
218 hinstance.ptr(),
219 lparam.unwrap_or_default() as _,
220 )
221 })
222 }
223
224 /// [`DefWindowProc`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowprocw)
225 /// function.
226 ///
227 /// The return type is variable, being defined by the `RetType` associated
228 /// type of the [`MsgSend`](crate::prelude::MsgSend) trait. That means each
229 /// message can define its own return type.
230 ///
231 /// # Safety
232 ///
233 /// Messages manipulate pointers, copies and window states. Improper use may
234 /// lead to undefined behavior.
235 pub unsafe fn DefWindowProc<M>(&self, msg: M) -> M::RetType
236 where
237 M: MsgSend,
238 {
239 let mut msg = msg;
240 let wm_any = msg.as_generic_wm();
241 unsafe {
242 msg.isize_to_ret(ffi::DefWindowProcW(
243 self.ptr(),
244 wm_any.msg_id.raw(),
245 wm_any.wparam,
246 wm_any.lparam,
247 ))
248 }
249 }
250
251 /// [`DestroyWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroywindow)
252 /// function.
253 ///
254 /// Usually you don't need to call this method directly, since it's
255 /// automatically called inside the internal message loop. The ordinary way
256 /// to close a window is sending a [`wm::Close`](crate::msg::wm::Close)
257 /// message.
258 pub fn DestroyWindow(&self) -> SysResult<()> {
259 bool_to_sysresult(unsafe { ffi::DestroyWindow(self.ptr()) })
260 }
261
262 /// [`DragDetect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dragdetect)
263 /// function.
264 #[must_use]
265 pub fn DragDetect(&self, pt: POINT) -> bool {
266 unsafe { ffi::DragDetect(self.ptr(), pt.x, pt.y) != 0 }
267 }
268
269 /// [`DrawCaption`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawcaption)
270 /// function.
271 pub fn DrawCaption(&self, hdc: &HDC, rect: RECT, flags: Option<co::DC>) -> SysResult<()> {
272 bool_to_sysresult(unsafe {
273 ffi::DrawCaption(self.ptr(), hdc.ptr(), pcvoid(&rect), flags.unwrap_or_default().raw())
274 })
275 }
276
277 /// [`DrawMenuBar`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawmenubar)
278 /// function.
279 pub fn DrawMenuBar(&self) -> SysResult<()> {
280 bool_to_sysresult(unsafe { ffi::DrawMenuBar(self.ptr()) })
281 }
282
283 /// [`EnableScrollBar`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enablescrollbar)
284 /// function.
285 pub fn EnableScrollBar(&self, sb_flags: co::SBB, arrows: co::ESB) -> SysResult<()> {
286 bool_to_sysresult(unsafe {
287 ffi::EnableScrollBar(self.ptr(), sb_flags.raw() as _, arrows.raw())
288 })
289 }
290
291 /// [`EnableWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enablewindow)
292 /// function.
293 pub fn EnableWindow(&self, enable: bool) -> bool {
294 unsafe { ffi::EnableWindow(self.ptr(), enable as _) != 0 }
295 }
296
297 /// [`EndDialog`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enddialog)
298 /// function.
299 pub fn EndDialog(&self, result: isize) -> SysResult<()> {
300 bool_to_sysresult(unsafe { ffi::EndDialog(self.ptr(), result) })
301 }
302
303 /// [`EnumChildWindows`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumchildwindows)
304 /// function.
305 ///
306 /// # Examples
307 ///
308 /// ```no_run
309 /// use winsafe::{self as w, prelude::*};
310 ///
311 /// let hwnd: w::HWND; // initialized somewhere
312 /// # let hwnd = w::HWND::NULL;
313 ///
314 /// hwnd.EnumChildWindows(|hchild: w::HWND| -> bool {
315 /// println!("Child HWND: {}", hchild);
316 /// true
317 /// });
318 /// ```
319 pub fn EnumChildWindows<F>(&self, func: F)
320 where
321 F: FnMut(HWND) -> bool,
322 {
323 unsafe {
324 ffi::EnumChildWindows(
325 self.ptr(),
326 callbacks::hwnd_enum_child_windows::<F> as _, // https://redd.it/npehj9
327 pcvoid(&func),
328 );
329 }
330 }
331
332 /// [`FindWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindoww)
333 /// function.
334 #[must_use]
335 pub fn FindWindow(class_name: Option<AtomStr>, title: Option<&str>) -> SysResult<Option<HWND>> {
336 let ptr = unsafe {
337 ffi::FindWindowW(
338 class_name.as_ref().map_or(std::ptr::null(), |c| c.as_ptr()),
339 WString::from_opt_str(title).as_ptr(),
340 )
341 };
342
343 if ptr.is_null() {
344 match GetLastError() {
345 co::ERROR::SUCCESS => Ok(None), // no window found
346 err => Err(err), // actual error
347 }
348 } else {
349 Ok(Some(unsafe { HWND::from_ptr(ptr) }))
350 }
351 }
352
353 /// [`FindWindowEx`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindowexw)
354 /// function.
355 #[must_use]
356 pub fn FindWindowEx(
357 &self,
358 hwnd_child_after: Option<&HWND>,
359 class_name: AtomStr,
360 title: Option<&str>,
361 ) -> SysResult<Option<HWND>> {
362 let ptr = unsafe {
363 ffi::FindWindowExW(
364 self.ptr(),
365 hwnd_child_after.map_or(std::ptr::null_mut(), |h| h.ptr()),
366 class_name.as_ptr(),
367 WString::from_opt_str(title).as_ptr(),
368 )
369 };
370
371 if ptr.is_null() {
372 match GetLastError() {
373 co::ERROR::SUCCESS => Ok(None), // no window found
374 err => Err(err), // actual error
375 }
376 } else {
377 Ok(Some(unsafe { HWND::from_ptr(ptr) }))
378 }
379 }
380
381 /// [`GetActiveWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getactivewindow)
382 /// function.
383 #[must_use]
384 pub fn GetActiveWindow() -> Option<HWND> {
385 ptr_to_option_handle(unsafe { ffi::GetActiveWindow() })
386 }
387
388 /// [`GetAltTabInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getalttabinfow)
389 /// function.
390 ///
391 /// If `item` is `None`, the item text is not retrieved.
392 ///
393 /// The `sz_item_text` is the maximum number of expected chars for the item
394 /// text. If `None`, defaults to 100.
395 pub fn GetAltTabInfo(
396 &self,
397 item: Option<u32>,
398 ati: &mut ALTTABINFO,
399 sz_item_text: Option<u32>,
400 ) -> SysResult<String> {
401 let buf_sz = sz_item_text.unwrap_or(100) + 1;
402 let mut buf = match item {
403 None => WString::new(),
404 Some(_) => WString::new_alloc_buf(buf_sz as _), // room for terminating null
405 };
406
407 bool_to_sysresult(unsafe {
408 ffi::GetAltTabInfoW(
409 self.ptr(),
410 item.map_or(-1, |item| item as i32),
411 pvoid(ati),
412 item.map_or(std::ptr::null_mut(), |_| buf.as_mut_ptr()),
413 buf_sz,
414 )
415 })
416 .map(|_| buf.to_string())
417 }
418
419 /// [`GetAncestor`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getancestor)
420 /// function.
421 #[must_use]
422 pub fn GetAncestor(&self, flags: co::GA) -> Option<HWND> {
423 ptr_to_option_handle(unsafe { ffi::GetAncestor(self.ptr(), flags.raw()) })
424 }
425
426 /// [`GetCapture`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcapture)
427 /// function.
428 #[must_use]
429 pub fn GetCapture() -> Option<HWND> {
430 ptr_to_option_handle(unsafe { ffi::GetCapture() })
431 }
432
433 /// [`GetClassLongPtr`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclasslongptrw)
434 /// function.
435 ///
436 /// If you just want to check whether the window is a dialog, prefer using
437 /// [`HWND::is_dialog`](crate::HWND::is_dialog) method.
438 #[must_use]
439 pub fn GetClassLongPtr(&self, index: co::GCLP) -> usize {
440 unsafe { ffi::GetClassLongPtrW(self.ptr(), index.raw()) }
441 }
442
443 /// [`GetClassName`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclassnamew)
444 /// function.
445 #[must_use]
446 pub fn GetClassName(&self) -> SysResult<String> {
447 let mut buf = WString::new_alloc_buf(256 + 1); // according to WNDCLASSEX docs
448 bool_to_sysresult(unsafe {
449 ffi::GetClassNameW(self.ptr(), buf.as_mut_ptr(), buf.buf_len() as _)
450 })
451 .map(|_| buf.to_string())
452 }
453
454 /// [`GetClientRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclientrect)
455 /// function.
456 #[must_use]
457 pub fn GetClientRect(&self) -> SysResult<RECT> {
458 let mut rc = RECT::default();
459 bool_to_sysresult(unsafe { ffi::GetClientRect(self.ptr(), pvoid(&mut rc)) }).map(|_| rc)
460 }
461
462 /// [`GetDC`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc)
463 /// function.
464 ///
465 /// # Examples
466 ///
467 /// Retrieving the device context of the desktop window:
468 ///
469 /// ```no_run
470 /// use winsafe::{self as w, prelude::*};
471 ///
472 /// let hdc_desktop = w::HWND::DESKTOP.GetDC()?;
473 /// # w::SysResult::Ok(())
474 /// ```
475 #[must_use]
476 pub fn GetDC(&self) -> SysResult<ReleaseDCGuard<'_>> {
477 unsafe {
478 ptr_to_sysresult_handle(ffi::GetDC(self.ptr())).map(|h| ReleaseDCGuard::new(self, h))
479 }
480 }
481
482 /// [`GetDCEx`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdcex)
483 /// function.
484 #[must_use]
485 pub fn GetDCEx(&self, hrgn_clip: &HRGN, flags: co::DCX) -> SysResult<ReleaseDCGuard<'_>> {
486 unsafe {
487 ptr_to_sysresult_handle(ffi::GetDCEx(self.ptr(), hrgn_clip.ptr(), flags.raw()))
488 .map(|h| ReleaseDCGuard::new(self, h))
489 }
490 }
491
492 /// [`GetDesktopWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdesktopwindow)
493 /// function.
494 #[must_use]
495 pub fn GetDesktopWindow() -> HWND {
496 unsafe { HWND::from_ptr(ffi::GetDesktopWindow()) }
497 }
498
499 /// [`GetDialogDpiChangeBehavior`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdialogdpichangebehavior)
500 /// function.
501 #[must_use]
502 pub fn GetDialogDpiChangeBehavior(&self) -> SysResult<co::DDC> {
503 match unsafe { co::DDC::from_raw(ffi::GetDialogDpiChangeBehavior(self.ptr())) } {
504 co::DDC::DEFAULT => match GetLastError() {
505 co::ERROR::SUCCESS => Ok(co::DDC::DEFAULT), // actual return value is zero
506 err => Err(err),
507 },
508 ddc => Ok(ddc),
509 }
510 }
511
512 /// [`GetDlgCtrlID`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdlgctrlid)
513 /// function.
514 #[must_use]
515 pub fn GetDlgCtrlID(&self) -> SysResult<u16> {
516 SetLastError(co::ERROR::SUCCESS);
517 match unsafe { ffi::GetDlgCtrlID(self.ptr()) } {
518 0 => match GetLastError() {
519 co::ERROR::SUCCESS => Ok(0), // actual ID is zero
520 err => Err(err),
521 },
522 id => Ok(id as _),
523 }
524 }
525
526 /// [`GetDlgItem`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdlgitem)
527 /// function.
528 #[must_use]
529 pub fn GetDlgItem(&self, ctrl_id: u16) -> SysResult<HWND> {
530 ptr_to_sysresult_handle(unsafe { ffi::GetDlgItem(self.ptr(), ctrl_id as _) })
531 }
532
533 /// [`GetDpiForWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow)
534 /// function.
535 #[must_use]
536 pub fn GetDpiForWindow(&self) -> u32 {
537 unsafe { ffi::GetDpiForWindow(self.ptr()) }
538 }
539
540 /// [`GetFocus`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getfocus)
541 /// function.
542 #[must_use]
543 pub fn GetFocus() -> Option<HWND> {
544 ptr_to_option_handle(unsafe { ffi::GetFocus() })
545 }
546
547 /// [`GetForegroundWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getforegroundwindow)
548 /// function.
549 #[must_use]
550 pub fn GetForegroundWindow() -> Option<HWND> {
551 ptr_to_option_handle(unsafe { ffi::GetForegroundWindow() })
552 }
553
554 /// [`GetLastActivePopup`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getlastactivepopup)
555 /// function.
556 #[must_use]
557 pub fn GetLastActivePopup(&self) -> Option<HWND> {
558 ptr_to_option_handle(unsafe { ffi::GetLastActivePopup(self.ptr()) })
559 }
560
561 /// [`GetMenu`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmenu)
562 /// function.
563 #[must_use]
564 pub fn GetMenu(&self) -> Option<HMENU> {
565 ptr_to_option_handle(unsafe { ffi::GetMenu(self.ptr()) })
566 }
567
568 /// [`GetMenuBarInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmenubarinfo)
569 /// function.
570 pub fn GetMenuBarInfo(
571 &self,
572 obj_id: co::OBJID,
573 item_id: u32,
574 mbi: &mut MENUBARINFO,
575 ) -> SysResult<()> {
576 bool_to_sysresult(unsafe {
577 ffi::GetMenuBarInfo(self.ptr(), obj_id.raw() as _, item_id as _, pvoid(mbi))
578 })
579 }
580
581 /// [`GetMenuItemRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmenuitemrect)
582 /// function.
583 #[must_use]
584 pub fn GetMenuItemRect(&self, hmenu: &HMENU, item_pos: u32) -> SysResult<RECT> {
585 let mut rc = RECT::default();
586 bool_to_sysresult(unsafe {
587 ffi::GetMenuItemRect(self.ptr(), hmenu.ptr(), item_pos, pvoid(&mut rc))
588 })
589 .map(|_| rc)
590 }
591
592 /// [`GetNextDlgGroupItem`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getnextdlggroupitem)
593 /// function.
594 #[must_use]
595 pub fn GetNextDlgGroupItem(&self, hwnd_ctrl: &HWND, previous: bool) -> SysResult<HWND> {
596 ptr_to_sysresult_handle(unsafe {
597 ffi::GetNextDlgGroupItem(self.ptr(), hwnd_ctrl.ptr(), previous as _)
598 })
599 }
600
601 /// [`GetNextDlgTabItem`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getnextdlgtabitem)
602 /// function.
603 #[must_use]
604 pub fn GetNextDlgTabItem(&self, hwnd_ctrl: &HWND, previous: bool) -> SysResult<HWND> {
605 ptr_to_sysresult_handle(unsafe {
606 ffi::GetNextDlgTabItem(self.ptr(), hwnd_ctrl.ptr(), previous as _)
607 })
608 }
609
610 /// [`GetParent`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getparent)
611 /// function.
612 #[must_use]
613 pub fn GetParent(&self) -> SysResult<HWND> {
614 ptr_to_sysresult_handle(unsafe { ffi::GetParent(self.ptr()) })
615 }
616
617 /// [`GetScrollInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getscrollinfo)
618 /// function.
619 pub fn GetScrollInfo(&self, bar: co::SBB, si: &mut SCROLLINFO) -> SysResult<()> {
620 bool_to_sysresult(unsafe { ffi::GetScrollInfo(self.ptr(), bar.raw(), pvoid(si)) })
621 }
622
623 /// [`GetScrollPos`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getscrollpos)
624 /// function.
625 #[must_use]
626 pub fn GetScrollPos(&self, bar: co::SBB) -> SysResult<i32> {
627 match unsafe { ffi::GetScrollPos(self.ptr(), bar.raw()) } {
628 0 => match GetLastError() {
629 co::ERROR::SUCCESS => Ok(0), // actual zero position
630 err => Err(err),
631 },
632 pos => Ok(pos),
633 }
634 }
635
636 /// [`GetShellWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getshellwindow)
637 /// function.
638 #[must_use]
639 pub fn GetShellWindow() -> Option<HWND> {
640 ptr_to_option_handle(unsafe { ffi::GetShellWindow() })
641 }
642
643 /// [`GetSystemMenu`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmenu)
644 /// function.
645 #[must_use]
646 pub fn GetSystemMenu(&self, revert: bool) -> Option<HMENU> {
647 ptr_to_option_handle(unsafe { ffi::GetSystemMenu(self.ptr(), revert as _) })
648 }
649
650 /// [`GetTopWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-gettopwindow)
651 /// function.
652 #[must_use]
653 pub fn GetTopWindow(&self) -> SysResult<Option<HWND>> {
654 match ptr_to_option_handle(unsafe { ffi::GetTopWindow(self.ptr()) }) {
655 None => match GetLastError() {
656 co::ERROR::SUCCESS => Ok(None), // no child window
657 err => Err(err),
658 },
659 Some(h) => Ok(Some(h)),
660 }
661 }
662
663 /// [`GetUpdateRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getupdaterect)
664 /// function.
665 #[must_use]
666 pub fn GetUpdateRect(&self, erase: bool) -> Option<RECT> {
667 let mut rc = RECT::default();
668 zero_as_none(unsafe { ffi::GetUpdateRect(self.ptr(), pvoid(&mut rc), erase as _) } as _)
669 .map(|_| rc)
670 }
671
672 /// [`GetUpdateRgn`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getupdatergn)
673 /// function.
674 #[must_use]
675 pub fn GetUpdateRgn(&self, hrgn: &HRGN, erase: bool) -> SysResult<co::REGION> {
676 match unsafe { ffi::GetUpdateRgn(self.ptr(), hrgn.ptr(), erase as _) } {
677 0 => Err(GetLastError()),
678 ret => Ok(unsafe { co::REGION::from_raw(ret) }),
679 }
680 }
681
682 /// [`GetWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindow)
683 /// function.
684 #[must_use]
685 pub fn GetWindow(&self, cmd: co::GW) -> SysResult<HWND> {
686 ptr_to_sysresult_handle(unsafe { ffi::GetWindow(self.ptr(), cmd.raw()) })
687 }
688
689 /// [`GetWindowDC`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdc)
690 /// function.
691 #[must_use]
692 pub fn GetWindowDC(&self) -> SysResult<ReleaseDCGuard<'_>> {
693 unsafe {
694 ptr_to_sysresult_handle(ffi::GetWindowDC(self.ptr()))
695 .map(|h| ReleaseDCGuard::new(self, h))
696 }
697 }
698
699 /// [`GetWindowDisplayAffinity`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdisplayaffinity)
700 /// function.
701 #[must_use]
702 pub fn GetWindowDisplayAffinity(&self) -> SysResult<co::WDA> {
703 let mut affinity = co::WDA::default();
704 bool_to_sysresult(unsafe {
705 ffi::GetWindowDisplayAffinity(self.ptr(), pvoid(&mut affinity))
706 })
707 .map(|_| affinity)
708 }
709
710 /// [`GetWindowDpiHostingBehavior`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdpihostingbehavior)
711 /// function.
712 #[must_use]
713 pub fn GetWindowDpiHostingBehavior(&self) -> co::DPI_HOSTING_BEHAVIOR {
714 unsafe { co::DPI_HOSTING_BEHAVIOR::from_raw(ffi::GetWindowDpiHostingBehavior(self.ptr())) }
715 }
716
717 /// [`GetWindowInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowinfo)
718 /// function.
719 pub fn GetWindowInfo(&self, wi: &mut WINDOWINFO) -> SysResult<()> {
720 bool_to_sysresult(unsafe { ffi::GetWindowInfo(self.ptr(), pvoid(wi)) })
721 }
722
723 /// [`GetWindowLong`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongw)
724 /// function (x32) or
725 /// [`GetWindowLongPtr`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw)
726 /// function (x64).
727 ///
728 /// If you just want to retrieve the window [`HINSTANCE`](crate::HINSTANCE),
729 /// prefer using [`HWND::hinstance`](crate::HWND::hinstance).
730 ///
731 /// If you just want to retrieve the window styles, prefer using
732 /// [`HWND::style`](crate::HWND::style) and
733 /// [`HWND::style_ex`](crate::HWND::style_ex).
734 #[must_use]
735 pub fn GetWindowLongPtr(&self, index: co::GWLP) -> isize {
736 #[cfg(target_pointer_width = "32")]
737 unsafe {
738 ffi::GetWindowLongW(self.ptr(), index.raw())
739 }
740
741 #[cfg(target_pointer_width = "64")]
742 unsafe {
743 ffi::GetWindowLongPtrW(self.ptr(), index.raw())
744 }
745 }
746
747 /// [`GetWindowModuleFileName`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowmodulefilenamew)
748 /// function.
749 #[must_use]
750 pub fn GetWindowModuleFileName(&self) -> String {
751 let mut buf = WString::new_alloc_buf(MAX_PATH + 1);
752 unsafe {
753 ffi::GetWindowModuleFileNameW(self.ptr(), buf.as_mut_ptr(), buf.buf_len() as u32 - 1);
754 }
755 buf.to_string()
756 }
757
758 /// [`GetWindowPlacement`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowplacement)
759 /// function.
760 pub fn GetWindowPlacement(&self, wp: &mut WINDOWPLACEMENT) -> SysResult<()> {
761 bool_to_sysresult(unsafe { ffi::GetWindowPlacement(self.ptr(), pvoid(wp)) })
762 }
763
764 /// [`GetWindowRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect)
765 /// function.
766 #[must_use]
767 pub fn GetWindowRect(&self) -> SysResult<RECT> {
768 let mut rc = RECT::default();
769 bool_to_sysresult(unsafe { ffi::GetWindowRect(self.ptr(), pvoid(&mut rc)) }).map(|_| rc)
770 }
771
772 /// [`GetWindowRgn`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrgn)
773 /// function.
774 #[must_use]
775 pub fn GetWindowRgn(&self, hrgn: &HRGN) -> SysResult<co::REGION> {
776 match unsafe { ffi::GetWindowRgn(self.ptr(), hrgn.ptr()) } {
777 0 => Err(GetLastError()),
778 ret => Ok(unsafe { co::REGION::from_raw(ret) }),
779 }
780 }
781
782 /// [`GetWindowRgnBox`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrgnbox)
783 /// function.
784 #[must_use]
785 pub fn GetWindowRgnBox(&self) -> SysResult<(RECT, co::REGION)> {
786 let mut rc = RECT::default();
787 match unsafe { ffi::GetWindowRgnBox(self.ptr(), pvoid(&mut rc)) } {
788 0 => Err(GetLastError()),
789 ret => Ok((rc, unsafe { co::REGION::from_raw(ret) })),
790 }
791 }
792
793 /// [`GetWindowText`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextw)
794 /// function.
795 ///
796 /// Calls
797 /// [`GetWindowTextLength`](crate::HWND::GetWindowTextLength) and performs
798 /// all necessary allocations, returning an ordinary
799 /// [`String`](std::string::String).
800 ///
801 /// ```no_run
802 /// use winsafe::{self as w, prelude::*};
803 ///
804 /// let hwnd: w::HWND; // initialized somewhere
805 /// # let hwnd = w::HWND::NULL;
806 ///
807 /// let text = hwnd.GetWindowText()?;
808 /// println!("Text: {}", text);
809 /// # w::SysResult::Ok(())
810 /// ```
811 #[must_use]
812 pub fn GetWindowText(&self) -> SysResult<String> {
813 let len = self.GetWindowTextLength()?;
814 if len == 0 {
815 return Ok(String::new()); // window has no text
816 }
817
818 let mut buf = WString::new_alloc_buf(len as usize + 1); // plus terminating null
819 match unsafe { ffi::GetWindowTextW(self.ptr(), buf.as_mut_ptr(), len + 1) } {
820 0 => match GetLastError() {
821 co::ERROR::SUCCESS => Ok(String::new()), // no chars copied for some reason
822 err => Err(err),
823 },
824 _ => Ok(buf.to_string()),
825 }
826 }
827
828 /// [`GetWindowTextLength`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextlengthw)
829 /// function.
830 ///
831 /// Does not count the terminating null.
832 ///
833 /// You usually don't need to call this method directly, since
834 /// [`GetWindowText`](crate::HWND::GetWindowText) returns a
835 /// [`String`](std::string::String), performing all necessary allocations.
836 #[must_use]
837 pub fn GetWindowTextLength(&self) -> SysResult<i32> {
838 SetLastError(co::ERROR::SUCCESS);
839 match unsafe { ffi::GetWindowTextLengthW(self.ptr()) } {
840 0 => match GetLastError() {
841 co::ERROR::SUCCESS => Ok(0), // actual zero length
842 err => Err(err),
843 },
844 len => Ok(len),
845 }
846 }
847
848 /// [`GetWindowThreadProcessId`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowthreadprocessid)
849 /// function.
850 ///
851 /// Returns thread ID and process ID, respectively.
852 #[must_use]
853 pub fn GetWindowThreadProcessId(&self) -> (u32, u32) {
854 let mut proc_id = 0u32;
855 let thread_id = unsafe { ffi::GetWindowThreadProcessId(self.ptr(), &mut proc_id) };
856 (thread_id, proc_id)
857 }
858
859 /// [`HideCaret`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-hidecaret)
860 /// function.
861 pub fn HideCaret(&self) -> SysResult<()> {
862 bool_to_sysresult(unsafe { ffi::HideCaret(self.ptr()) })
863 }
864
865 /// [`HiliteMenuItem`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-hilitemenuitem)
866 /// function.
867 pub fn HiliteMenuItem(&self, hmenu: &HMENU, id_or_pos: IdPos, hilite: bool) -> bool {
868 unsafe {
869 ffi::HiliteMenuItem(
870 self.ptr(),
871 hmenu.ptr(),
872 id_or_pos.id_or_pos_u32(),
873 id_or_pos.mf_flag().raw()
874 | if hilite { co::MF::HILITE } else { co::MF::UNHILITE }.raw(),
875 ) != 0
876 }
877 }
878
879 /// [`InheritWindowMonitor`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-inheritwindowmonitor)
880 /// function.
881 pub fn InheritWindowMonitor(&self, hwnd_inherit: &HWND) -> SysResult<()> {
882 bool_to_sysresult(unsafe { ffi::InheritWindowMonitor(self.ptr(), hwnd_inherit.ptr()) })
883 }
884
885 /// [`InvalidateRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-invalidaterect)
886 /// function.
887 ///
888 /// # Examples
889 ///
890 /// Most of the time you'll just want update the entire client area:
891 ///
892 /// ```no_run
893 /// use winsafe::{self as w, prelude::*};
894 ///
895 /// let hwnd: w::HWND; // initialized somewhere
896 /// # let hwnd = w::HWND::NULL;
897 ///
898 /// hwnd.InvalidateRect(None, true)?;
899 /// # w::SysResult::Ok(())
900 /// ```
901 pub fn InvalidateRect(&self, rc: Option<&RECT>, erase: bool) -> SysResult<()> {
902 bool_to_sysresult(unsafe {
903 ffi::InvalidateRect(self.ptr(), pcvoid_or_null(rc), erase as _)
904 })
905 }
906
907 /// [`InvalidateRgn`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-invalidatergn)
908 /// function.
909 pub fn InvalidateRgn(&self, hrgn: &HRGN, erase: bool) {
910 unsafe {
911 ffi::InvalidateRgn(self.ptr(), hrgn.ptr(), erase as _);
912 }
913 }
914
915 /// [`IsChild`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-ischild)
916 /// function.
917 #[must_use]
918 pub fn IsChild(&self, hwnd_possible_child: &HWND) -> bool {
919 unsafe { ffi::IsChild(self.ptr(), hwnd_possible_child.ptr()) != 0 }
920 }
921
922 /// [`IsDialogMessage`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isdialogmessagew)
923 /// function.
924 #[must_use]
925 pub fn IsDialogMessage(&self, msg: &mut MSG) -> bool {
926 unsafe { ffi::IsDialogMessageW(self.ptr(), pvoid(msg)) != 0 }
927 }
928
929 /// [`IsIconic`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isiconic)
930 /// function.
931 #[must_use]
932 pub fn IsIconic(&self) -> bool {
933 unsafe { ffi::IsIconic(self.ptr()) != 0 }
934 }
935
936 /// [`IsWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindow)
937 /// function.
938 #[must_use]
939 pub fn IsWindow(&self) -> bool {
940 unsafe { ffi::IsWindow(self.ptr()) != 0 }
941 }
942
943 /// [`IsWindowEnabled`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindowenabled)
944 /// function.
945 #[must_use]
946 pub fn IsWindowEnabled(&self) -> bool {
947 unsafe { ffi::IsWindowEnabled(self.ptr()) != 0 }
948 }
949
950 /// [`IsWindowUnicode`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindowunicode)
951 /// function.
952 #[must_use]
953 pub fn IsWindowUnicode(&self) -> bool {
954 unsafe { ffi::IsWindowUnicode(self.ptr()) != 0 }
955 }
956
957 /// [`IsWindowVisible`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindowvisible)
958 /// function.
959 #[must_use]
960 pub fn IsWindowVisible(&self) -> bool {
961 unsafe { ffi::IsWindowVisible(self.ptr()) != 0 }
962 }
963
964 /// [`IsZoomed`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iszoomed)
965 /// function.
966 #[must_use]
967 pub fn IsZoomed(&self) -> bool {
968 unsafe { ffi::IsZoomed(self.ptr()) != 0 }
969 }
970
971 /// [`KillTimer`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-killtimer)
972 /// function.
973 ///
974 /// This function ends the timer calls for the given timer ID. If you don't
975 /// call this function, the timer calls will continue until the window is
976 /// destroyed – at this point, any remaining timers will be automatically
977 /// cleared.
978 pub fn KillTimer(&self, event_id: usize) -> SysResult<()> {
979 match unsafe { ffi::KillTimer(self.ptr(), event_id) } {
980 0 => match GetLastError() {
981 co::ERROR::SUCCESS => Ok(()),
982 e => Err(e),
983 },
984 _ => Ok(()),
985 }
986 }
987
988 /// [`LockWindowUpdate`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-lockwindowupdate)
989 /// function.
990 ///
991 /// # Examples
992 ///
993 /// ```no_run
994 /// use winsafe::{self as w, prelude::*};
995 ///
996 /// let hwnd: w::HWND; // initialized somewhere
997 /// # let hwnd = w::HWND::NULL;
998 ///
999 /// // Lock the window – only one window can be locked at a time.
1000 /// hwnd.LockWindowUpdate()?;
1001 ///
1002 /// // After all operations, unlock the currently locked window.
1003 /// w::HWND::NULL.LockWindowUpdate()?;
1004 /// # w::SysResult::Ok(())
1005 /// ```
1006 pub fn LockWindowUpdate(&self) -> SysResult<()> {
1007 bool_to_sysresult(unsafe { ffi::LockWindowUpdate(self.ptr()) })
1008 }
1009
1010 /// [`LogicalToPhysicalPoint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-logicaltophysicalpoint)
1011 /// function.
1012 pub fn LogicalToPhysicalPoint(&self, pt: *mut POINT) -> SysResult<()> {
1013 bool_to_sysresult(unsafe { ffi::LogicalToPhysicalPoint(self.ptr(), pt as _) })
1014 }
1015
1016 /// [`MapDialogRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mapdialogrect)
1017 /// function.
1018 #[must_use]
1019 pub fn MapDialogRect(&self, rc: RECT) -> SysResult<RECT> {
1020 let mut buf = rc;
1021 bool_to_sysresult(unsafe { ffi::MapDialogRect(self.ptr(), pvoid(&mut buf)) }).map(|_| buf)
1022 }
1023
1024 /// [`MapWindowPoints`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mapwindowpoints)
1025 /// function.
1026 ///
1027 /// This method can convert either a series of [`POINT`](crate::POINT)
1028 /// structs or a single [`RECT`](crate::RECT).
1029 ///
1030 /// # Examples
1031 ///
1032 /// ```no_run
1033 /// use winsafe::{self as w, prelude::*};
1034 ///
1035 /// let hwnd: w::HWND; // initialized somewhere
1036 /// # let hwnd = w::HWND::NULL;
1037 /// let hwnd_dest: w::HWND;
1038 /// # let hwnd_dest = w::HWND::NULL;
1039 ///
1040 /// let mut points = vec![w::POINT::default(), w::POINT::default()];
1041 ///
1042 /// hwnd.MapWindowPoints(
1043 /// &hwnd_dest,
1044 /// w::PtsRc::Pts(&mut points),
1045 /// )?;
1046 /// # w::SysResult::Ok(())
1047 /// ```
1048 pub fn MapWindowPoints(&self, hdest: &HWND, points: PtsRc) -> SysResult<(i16, i16)> {
1049 let forced_pts = match points {
1050 PtsRc::Pts(pts) => pts,
1051 PtsRc::Rc(rc) => unsafe { std::slice::from_raw_parts_mut(rc as *mut _ as _, 2) },
1052 };
1053
1054 SetLastError(co::ERROR::SUCCESS);
1055 match unsafe {
1056 ffi::MapWindowPoints(
1057 self.ptr(),
1058 hdest.ptr(),
1059 forced_pts.as_mut_ptr() as _,
1060 forced_pts.len() as _,
1061 )
1062 } {
1063 0 => Err(GetLastError()),
1064 n => Ok((LOWORD(n as _) as _, HIWORD(n as _) as _)),
1065 }
1066 }
1067
1068 /// [`MessageBox`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw)
1069 /// function.
1070 ///
1071 /// Consider using the more modern
1072 /// [`HWND::TaskDialog`](crate::HWND::TaskDialog) method.
1073 ///
1074 /// # Examples
1075 ///
1076 /// A modal message box, which blocks its parent:
1077 ///
1078 /// ```no_run
1079 /// use winsafe::{self as w, prelude::*, co};
1080 ///
1081 /// let hwnd: w::HWND; // initialized somewhere
1082 /// # let hwnd = w::HWND::NULL;
1083 ///
1084 /// hwnd.MessageBox("Hello, world", "title",
1085 /// co::MB::OKCANCEL | co::MB::ICONINFORMATION)?;
1086 /// # w::SysResult::Ok(())
1087 /// ```
1088 ///
1089 /// Usually the message box has a valid parent window, however, if for some
1090 /// reason you don't have a window to serve as parent, you still can show a
1091 /// non-modal, parent-less message box by using the null window handle:
1092 ///
1093 /// ```no_run
1094 /// use winsafe::{self as w, prelude::*, co};
1095 ///
1096 /// w::HWND::NULL
1097 /// .MessageBox("Hello, world", "Title", co::MB::ICONEXCLAMATION)?;
1098 /// # w::SysResult::Ok(())
1099 /// ```
1100 pub fn MessageBox(&self, text: &str, caption: &str, flags: co::MB) -> SysResult<co::DLGID> {
1101 match unsafe {
1102 ffi::MessageBoxW(
1103 self.ptr(),
1104 WString::from_str(text).as_ptr(),
1105 WString::from_str(caption).as_ptr(),
1106 flags.raw(),
1107 )
1108 } {
1109 0 => Err(GetLastError()),
1110 ret => Ok(unsafe { co::DLGID::from_raw(ret as _) }),
1111 }
1112 }
1113
1114 /// [`MonitorFromWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-monitorfromwindow)
1115 /// function.
1116 #[must_use]
1117 pub fn MonitorFromWindow(&self, flags: co::MONITOR) -> HMONITOR {
1118 unsafe { HMONITOR::from_ptr(ffi::MonitorFromWindow(self.ptr(), flags.raw())) }
1119 }
1120
1121 /// [`MoveWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-movewindow)
1122 /// function.
1123 pub fn MoveWindow(&self, pos: POINT, size: SIZE, repaint: bool) -> SysResult<()> {
1124 bool_to_sysresult(unsafe {
1125 ffi::MoveWindow(self.ptr(), pos.x, pos.y, size.cx, size.cy, repaint as _)
1126 })
1127 }
1128
1129 /// [`OpenClipboard`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-openclipboard)
1130 /// function.
1131 ///
1132 /// In the original C implementation, you must call
1133 /// [`CloseClipboard`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-closeclipboard)
1134 /// as a cleanup operation.
1135 ///
1136 /// Here, the cleanup is performed automatically, because `OpenClipboard`
1137 /// returns a [`CloseClipboardGuard`](crate::guard::CloseClipboardGuard),
1138 /// which automatically calls `CloseClipboard` when the guard goes out of
1139 /// scope. You must, however, keep the guard alive, otherwise the cleanup
1140 /// will be performed right away.
1141 ///
1142 /// # Examples
1143 ///
1144 /// ```no_run
1145 /// use winsafe::{self as w, prelude::*, co};
1146 ///
1147 /// let hwnd: w::HWND; // initialized somewhere
1148 /// # let hwnd = w::HWND::NULL;
1149 ///
1150 /// let hclip = hwnd.OpenClipboard()?;
1151 /// let data = hclip.GetClipboardData(co::CF::TEXT)?;
1152 /// # w::SysResult::Ok(())
1153 /// ```
1154 ///
1155 /// You can also open the clipboard without an `HWND` owner:
1156 ///
1157 /// ```no_run
1158 /// use winsafe::{self as w, prelude::*, co};
1159 ///
1160 /// let hclip = w::HWND::NULL.OpenClipboard()?;
1161 /// let data = hclip.GetClipboardData(co::CF::TEXT)?;
1162 /// # w::SysResult::Ok(())
1163 /// ```
1164 #[must_use]
1165 pub fn OpenClipboard(&self) -> SysResult<CloseClipboardGuard<'_>> {
1166 unsafe {
1167 bool_to_sysresult(ffi::OpenClipboard(self.ptr()))
1168 .map(|_| CloseClipboardGuard::new(self, HCLIPBOARD::INVALID))
1169 }
1170 }
1171
1172 /// [`PostMessage`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagew)
1173 /// function.
1174 ///
1175 /// Note that this method is asychronous.
1176 ///
1177 /// # Safety
1178 ///
1179 /// Messages manipulate pointers, copies and window states. Improper use may
1180 /// lead to undefined behavior.
1181 pub unsafe fn PostMessage<M>(&self, msg: M) -> SysResult<()>
1182 where
1183 M: MsgSend + Send + Copy + 'static,
1184 {
1185 let mut msg = msg;
1186 let wm_any = msg.as_generic_wm();
1187 bool_to_sysresult(unsafe {
1188 ffi::PostMessageW(self.ptr(), wm_any.msg_id.raw(), wm_any.wparam, wm_any.lparam)
1189 })
1190 }
1191
1192 /// [`RealChildWindowFromPoint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-realchildwindowfrompoint)
1193 /// function.
1194 #[must_use]
1195 pub fn RealChildWindowFromPoint(&self, pt_parent_client_coords: POINT) -> Option<HWND> {
1196 ptr_to_option_handle(unsafe {
1197 ffi::RealChildWindowFromPoint(
1198 self.ptr(),
1199 pt_parent_client_coords.x,
1200 pt_parent_client_coords.y,
1201 )
1202 })
1203 }
1204
1205 /// [`RealGetWindowClass`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-realgetwindowclassw)
1206 /// function.
1207 #[must_use]
1208 pub fn RealGetWindowClass(&self) -> SysResult<String> {
1209 let mut buf = WString::new_alloc_buf(256 + 1); // according to WNDCLASSEX docs
1210 bool_to_sysresult(unsafe {
1211 ffi::RealGetWindowClassW(self.ptr(), buf.as_mut_ptr(), buf.buf_len() as _)
1212 } as _)
1213 .map(|_| buf.to_string())
1214 }
1215
1216 /// [`RedrawWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-redrawwindow)
1217 /// function.
1218 pub fn RedrawWindow(
1219 &self,
1220 rc_update: RECT,
1221 hrgn_update: &HRGN,
1222 flags: co::RDW,
1223 ) -> SysResult<()> {
1224 bool_to_sysresult(unsafe {
1225 ffi::RedrawWindow(self.ptr(), pcvoid(&rc_update), hrgn_update.ptr(), flags.raw())
1226 })
1227 }
1228
1229 /// [`RegisterHotKey`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey)
1230 /// function.
1231 pub fn RegisterHotKey(&self, id: i32, modifiers: co::MOD, vkey_code: co::VK) -> SysResult<()> {
1232 bool_to_sysresult(unsafe {
1233 ffi::RegisterHotKey(self.ptr(), id, modifiers.raw() as _, vkey_code.raw() as _)
1234 })
1235 }
1236
1237 /// [`ScreenToClient`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-screentoclient)
1238 /// function.
1239 ///
1240 /// If you need to convert a [`RECT`](crate::RECT), see the
1241 /// [`HWND::ScreenToClientRc`](crate::HWND::ScreenToClientRc) function.
1242 #[must_use]
1243 pub fn ScreenToClient(&self, pt: POINT) -> SysResult<POINT> {
1244 let mut buf = pt;
1245 bool_to_sysresult(unsafe { ffi::ScreenToClient(self.ptr(), pvoid(&mut buf)) }).map(|_| buf)
1246 }
1247
1248 /// [`ScreenToClient`](crate::HWND::ScreenToClient) method for a
1249 /// [`RECT`](crate::RECT).
1250 #[must_use]
1251 pub fn ScreenToClientRc(&self, rc: RECT) -> SysResult<RECT> {
1252 let mut buf = rc;
1253 bool_to_sysresult(unsafe { ffi::ScreenToClient(self.ptr(), pvoid(&mut buf.left)) })?;
1254 bool_to_sysresult(unsafe { ffi::ScreenToClient(self.ptr(), pvoid(&mut buf.right)) })
1255 .map(|_| buf)
1256 }
1257
1258 /// [`ScrollWindowEx`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-scrollwindowex)
1259 /// function.
1260 pub fn ScrollWindowEx(
1261 &self,
1262 dx: i32,
1263 dy: i32,
1264 client_area_portion: Option<&RECT>,
1265 clipping_rect: Option<&RECT>,
1266 hrgn_update: Option<&HRGN>,
1267 updated_boundaries: Option<&mut RECT>,
1268 flags: co::SCROLLW,
1269 ) -> SysResult<co::REGION> {
1270 match unsafe {
1271 ffi::ScrollWindowEx(
1272 self.ptr(),
1273 dx,
1274 dy,
1275 pcvoid_or_null(client_area_portion),
1276 pcvoid_or_null(clipping_rect),
1277 hrgn_update.map_or(std::ptr::null_mut(), |h| h.ptr()),
1278 pvoid_or_null(updated_boundaries),
1279 flags.raw(),
1280 )
1281 } {
1282 0 => Err(GetLastError()),
1283 v => Ok(unsafe { co::REGION::from_raw(v) }),
1284 }
1285 }
1286
1287 /// [`SendMessage`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagew)
1288 /// function, specialized to send a [`wm::Command`](crate::msg::wm::Command)
1289 /// message.
1290 ///
1291 /// Unlike the general [`SendMessage`](crate::HWND::SendMessage), sending a
1292 /// command is safe.
1293 ///
1294 /// # Examples
1295 ///
1296 /// ```no_run
1297 /// use winsafe::{self as w, prelude::*, msg};
1298 ///
1299 /// let hwnd: w::HWND; // initialized somewhere
1300 /// # let hwnd = w::HWND::NULL;
1301 ///
1302 /// const ID_MENU_FILE_OPEN: u16 = 103;
1303 ///
1304 /// hwnd.SendCommand(
1305 /// w::AccelMenuCtrl::Menu(ID_MENU_FILE_OPEN),
1306 /// );
1307 /// ```
1308 pub fn SendCommand(&self, cmd: AccelMenuCtrl) {
1309 unsafe {
1310 self.SendMessage(wm::Command { event: cmd });
1311 }
1312 }
1313
1314 /// [`SendMessage`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagew)
1315 /// function.
1316 ///
1317 /// The return type is variable, being defined by the `RetType` associated
1318 /// type of the [`MsgSend`](crate::prelude::MsgSend) trait. That means each
1319 /// message can define its own return type.
1320 ///
1321 /// # Safety
1322 ///
1323 /// Messages manipulate pointers, copies and window states. Improper use may
1324 /// lead to undefined behavior.
1325 ///
1326 /// # Examples
1327 ///
1328 /// Sending a [`bm::GetImage`](crate::msg::bm::GetImage) button message,
1329 /// which demands an image type parameter. Note that this specific message
1330 /// can also return an error, which is handled with
1331 /// [`?`](https://doc.rust-lang.org/std/result/index.html#the-question-mark-operator-):
1332 ///
1333 /// ```no_run
1334 /// use winsafe::{self as w, prelude::*, co, msg};
1335 ///
1336 /// let hwnd: w::HWND; // initialized somewhere
1337 /// # let hwnd = w::HWND::NULL;
1338 ///
1339 /// let bmp = unsafe {
1340 /// hwnd.SendMessage(
1341 /// msg::bm::GetImage {
1342 /// img_type: co::IMAGE_TYPE::BITMAP,
1343 /// },
1344 /// )
1345 /// }?;
1346 /// # w::SysResult::Ok(())
1347 /// ```
1348 ///
1349 /// Sending an [`em::CharFromPos`](crate::msg::em::CharFromPos) edit message,
1350 /// which receives point coordinates and returns two values:
1351 ///
1352 /// ```no_run
1353 /// use winsafe::{self as w, prelude::*, msg};
1354 ///
1355 /// let hwnd: w::HWND; // initialized somewhere
1356 /// # let hwnd = w::HWND::NULL;
1357 ///
1358 /// let (char_pos, line_pos) = unsafe {
1359 /// hwnd.SendMessage(
1360 /// msg::em::CharFromPos {
1361 /// coords: w::POINT::with(12, 20),
1362 /// },
1363 /// )
1364 /// };
1365 /// ```
1366 pub unsafe fn SendMessage<M>(&self, msg: M) -> M::RetType
1367 where
1368 M: MsgSend,
1369 {
1370 let mut msg = msg;
1371 let wm_any = msg.as_generic_wm();
1372 unsafe {
1373 msg.isize_to_ret(ffi::SendMessageW(
1374 self.ptr(),
1375 wm_any.msg_id.raw(),
1376 wm_any.wparam,
1377 wm_any.lparam,
1378 ))
1379 }
1380 }
1381
1382 /// [`SendMessageTimeout`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagetimeoutw)
1383 /// function.
1384 ///
1385 /// # Safety
1386 ///
1387 /// Messages manipulate pointers, copies and window states. Improper use may
1388 /// lead to undefined behavior.
1389 pub unsafe fn SendMessageTimeout<M>(
1390 &self,
1391 msg: M,
1392 flags: co::SMTO,
1393 timeout_ms: u32,
1394 ) -> SysResult<M::RetType>
1395 where
1396 M: MsgSend,
1397 {
1398 let mut msg = msg;
1399 let wm_any = msg.as_generic_wm();
1400 let mut result = 0isize;
1401
1402 unsafe {
1403 bool_to_sysresult(ffi::SendMessageTimeoutW(
1404 self.ptr(),
1405 wm_any.msg_id.raw(),
1406 wm_any.wparam,
1407 wm_any.lparam,
1408 flags.raw(),
1409 timeout_ms,
1410 &mut result,
1411 ) as _)
1412 .map(|_| msg.isize_to_ret(result))
1413 }
1414 }
1415
1416 /// [`SetActiveWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setactivewindow)
1417 /// function.
1418 pub fn SetActiveWindow(&self) -> SysResult<HWND> {
1419 ptr_to_sysresult_handle(unsafe { ffi::SetActiveWindow(self.ptr()) })
1420 }
1421
1422 /// [`SetCapture`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setcapture)
1423 /// function.
1424 pub fn SetCapture(&self) -> ReleaseCaptureGuard<'_> {
1425 unsafe {
1426 ReleaseCaptureGuard::new(
1427 self,
1428 ffi::SetCapture(self.ptr())
1429 .as_mut()
1430 .map(|ptr| HWND::from_ptr(ptr)),
1431 )
1432 }
1433 }
1434
1435 /// [`SetDialogDpiChangeBehavior`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setdialogdpichangebehavior)
1436 /// function.
1437 pub fn SetDialogDpiChangeBehavior(&self, mask: co::DDC, values: co::DDC) -> SysResult<()> {
1438 bool_to_sysresult(unsafe {
1439 ffi::SetDialogDpiChangeBehavior(self.ptr(), mask.raw(), values.raw())
1440 })
1441 }
1442
1443 /// [`SetFocus`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setfocus)
1444 /// function.
1445 pub fn SetFocus(&self) -> Option<HWND> {
1446 ptr_to_option_handle(unsafe { ffi::SetFocus(self.ptr()) })
1447 }
1448
1449 /// [`SetForegroundWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setforegroundwindow)
1450 /// function.
1451 pub fn SetForegroundWindow(&self) -> bool {
1452 unsafe { ffi::SetForegroundWindow(self.ptr()) != 0 }
1453 }
1454
1455 /// [`SetLayeredWindowAttributes`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setlayeredwindowattributes)
1456 /// function.
1457 pub fn SetLayeredWindowAttributes(
1458 &self,
1459 transparency_color_key: COLORREF,
1460 alpha: u8,
1461 flags: co::LWA,
1462 ) -> SysResult<()> {
1463 bool_to_sysresult(unsafe {
1464 ffi::SetLayeredWindowAttributes(
1465 self.ptr(),
1466 transparency_color_key.raw(),
1467 alpha,
1468 flags.raw(),
1469 )
1470 })
1471 }
1472
1473 /// [`SetMenu`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setmenu)
1474 /// function.
1475 pub fn SetMenu(&self, hmenu: &HMENU) -> SysResult<()> {
1476 bool_to_sysresult(unsafe { ffi::SetMenu(self.ptr(), hmenu.ptr()) })
1477 }
1478
1479 /// [`SetParent`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent)
1480 /// function.
1481 pub fn SetParent(&self, hwnd_new_parent: &HWND) -> SysResult<Option<HWND>> {
1482 match ptr_to_option_handle(unsafe { ffi::SetParent(self.ptr(), hwnd_new_parent.ptr()) }) {
1483 None => match GetLastError() {
1484 co::ERROR::SUCCESS => Ok(None), // no previous parent
1485 err => Err(err),
1486 },
1487 Some(h) => Ok(Some(h)),
1488 }
1489 }
1490
1491 /// [`SetScrollInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setscrollinfo)
1492 /// function.
1493 pub fn SetScrollInfo(&self, bar: co::SBB, si: &SCROLLINFO, redraw: bool) -> i32 {
1494 unsafe { ffi::SetScrollInfo(self.ptr(), bar.raw(), pcvoid(si), redraw as _) }
1495 }
1496
1497 /// [`SetScrollPos`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setscrollpos)
1498 /// function.
1499 pub fn SetScrollPos(&self, b: co::SBB, pos: i32, redraw: bool) -> SysResult<i32> {
1500 match unsafe { ffi::SetScrollPos(self.ptr(), b.raw(), pos, redraw as _) } {
1501 0 => match GetLastError() {
1502 co::ERROR::SUCCESS => Ok(0), // actual zero position
1503 err => Err(err),
1504 },
1505 pos => Ok(pos),
1506 }
1507 }
1508
1509 /// [`SetScrollRange`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setscrollrange)
1510 /// function.
1511 pub fn SetScrollRange(
1512 &self,
1513 bar: co::SBB,
1514 min_pos: i32,
1515 max_pos: i32,
1516 redraw: bool,
1517 ) -> SysResult<()> {
1518 bool_to_sysresult(unsafe {
1519 ffi::SetScrollRange(self.ptr(), bar.raw(), min_pos, max_pos, redraw as _)
1520 })
1521 }
1522
1523 /// This method returns the timer ID, to be passed to
1524 /// [`HWND::KillTimer`](crate::HWND::KillTimer).
1525 ///
1526 /// The timer calls – either
1527 /// [`wm_timer`](crate::gui::events::WindowEvents::wm_timer) message or
1528 /// callback function – will continuously be executed until you call
1529 /// `KillTimer`. If you don't call `KillTimer`, the timer calls will
1530 /// continue until the window is destroyed – at this point, any remaining
1531 /// timers will be automatically cleared.
1532 ///
1533 /// # Why not closures?
1534 ///
1535 /// A common C++ technique to use closures with `SetTimer` is allocating a
1536 /// closure on the heap and use its pointer as the timer ID. When the
1537 /// callback function is called, the pointer is dereferenced and the closure
1538 /// is then executed.
1539 ///
1540 /// The problem with this approach is that the closure must be freed after
1541 /// `KillTimer`, which can be called from anywhere, including from the
1542 /// closure itself – that means you must keep the pointer outside the
1543 /// closure and free it somehow after the closure finishes.
1544 ///
1545 /// Such approach is, obviously, incredibly unsafe, and only possible within
1546 /// Rust's rigid ownership rules if we use some sort of garbage-collection,
1547 /// which will free the allocated closure some time after `KillTimer` is
1548 /// called and the closure itself finishes. Since that would incur in a
1549 /// performance penalty, the current implementation of `SetTimer` will only
1550 /// accept ordinary function pointers, not closures.
1551 ///
1552 /// Handling the `wm_timer` message is simply more practical and efficient,
1553 /// so the use of a callback is discouraged here.
1554 pub fn SetTimer(
1555 &self,
1556 event_id: usize,
1557 elapse_ms: u32,
1558 timer_func: Option<TIMERPROC>,
1559 ) -> SysResult<usize> {
1560 match unsafe {
1561 ffi::SetTimer(
1562 self.ptr(),
1563 event_id,
1564 elapse_ms,
1565 timer_func.map_or(std::ptr::null(), |lp| lp as _),
1566 )
1567 } {
1568 0 => Err(GetLastError()),
1569 tid => Ok(tid),
1570 }
1571 }
1572
1573 /// [`SetWindowDisplayAffinity`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowdisplayaffinity)
1574 /// function.
1575 pub fn SetWindowDisplayAffinity(&self, affinity: co::WDA) -> SysResult<()> {
1576 bool_to_sysresult(unsafe { ffi::SetWindowDisplayAffinity(self.ptr(), affinity.raw()) })
1577 }
1578
1579 /// [`SetWindowLongPtr`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlongptrw)
1580 /// function.
1581 ///
1582 /// If you just want to set the window styles, prefer using
1583 /// [`HWND::set_style`](crate::HWND::set_style) and
1584 /// [`HWND::set_style_ex`](crate::HWND::set_style_ex).
1585 ///
1586 /// # Safety
1587 ///
1588 /// Changing these values may potentially cause undefined behavior to the
1589 /// window, and passed pointers must be handled correctly.
1590 pub unsafe fn SetWindowLongPtr(&self, index: co::GWLP, new_long: isize) -> isize {
1591 #[cfg(target_pointer_width = "32")]
1592 unsafe {
1593 ffi::SetWindowLongW(self.ptr(), index.raw(), new_long)
1594 }
1595
1596 #[cfg(target_pointer_width = "64")]
1597 unsafe {
1598 ffi::SetWindowLongPtrW(self.ptr(), index.raw(), new_long)
1599 }
1600 }
1601
1602 /// [`SetWindowPlacement`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowplacement)
1603 /// function.
1604 pub fn SetWindowPlacement(&self, wp: &WINDOWPLACEMENT) -> SysResult<()> {
1605 bool_to_sysresult(unsafe { ffi::SetWindowPlacement(self.ptr(), pcvoid(wp)) })
1606 }
1607
1608 /// [`SetWindowPos`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos)
1609 /// function.
1610 ///
1611 /// # Examples
1612 ///
1613 /// ```no_run
1614 /// use winsafe::{self as w, prelude::*, co};
1615 ///
1616 /// let hwnd: w::HWND; // initialized somewhere
1617 /// # let hwnd = w::HWND::NULL;
1618 ///
1619 /// hwnd.SetWindowPos(
1620 /// w::HwndPlace::None,
1621 /// w::POINT::with(10, 10),
1622 /// w::SIZE::default(),
1623 /// co::SWP::NOZORDER | co::SWP::NOSIZE,
1624 /// )?;
1625 /// # w::SysResult::Ok(())
1626 /// ```
1627 pub fn SetWindowPos(
1628 &self,
1629 hwnd_insert_after: HwndPlace,
1630 pos: POINT,
1631 size: SIZE,
1632 flags: co::SWP,
1633 ) -> SysResult<()> {
1634 bool_to_sysresult(unsafe {
1635 ffi::SetWindowPos(
1636 self.ptr(),
1637 hwnd_insert_after.as_ptr(),
1638 pos.x,
1639 pos.y,
1640 size.cx,
1641 size.cy,
1642 flags.raw(),
1643 )
1644 })
1645 }
1646
1647 /// [`SetWindowRgn`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowrgn)
1648 /// function.
1649 pub fn SetWindowRgn(&self, hrgn: &HRGN, redraw: bool) -> SysResult<()> {
1650 bool_to_sysresult(unsafe { ffi::SetWindowRgn(self.ptr(), hrgn.ptr(), redraw as _) })
1651 }
1652
1653 /// [`SetWindowText`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowtextw)
1654 /// function.
1655 pub fn SetWindowText(&self, text: &str) -> SysResult<()> {
1656 bool_to_sysresult(unsafe {
1657 ffi::SetWindowTextW(self.ptr(), WString::from_str(text).as_ptr())
1658 })
1659 }
1660
1661 /// [`ShowCaret`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showcaret)
1662 /// function.
1663 pub fn ShowCaret(&self) -> SysResult<()> {
1664 bool_to_sysresult(unsafe { ffi::ShowCaret(self.ptr()) })
1665 }
1666
1667 /// [`ShowOwnedPopups`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showownedpopups)
1668 /// function.
1669 pub fn ShowOwnedPopups(&self, show: bool) -> SysResult<()> {
1670 bool_to_sysresult(unsafe { ffi::ShowOwnedPopups(self.ptr(), show as _) })
1671 }
1672
1673 /// [`ShowWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow)
1674 /// function.
1675 pub fn ShowWindow(&self, show_cmd: co::SW) -> bool {
1676 unsafe { ffi::ShowWindow(self.ptr(), show_cmd.raw()) != 0 }
1677 }
1678
1679 /// [`ShowWindowAsync`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindowasync)
1680 /// function.
1681 pub fn ShowWindowAsync(&self, show_cmd: co::SW) -> SysResult<()> {
1682 bool_to_sysresult(unsafe { ffi::ShowWindowAsync(self.ptr(), show_cmd.raw()) })
1683 }
1684
1685 /// [`ShutdownBlockReasonCreate`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-shutdownblockreasoncreate)
1686 /// function.
1687 pub fn ShutdownBlockReasonCreate(&self, reason: &str) -> SysResult<()> {
1688 bool_to_sysresult(unsafe {
1689 ffi::ShutdownBlockReasonCreate(self.ptr(), WString::from_str(reason).as_ptr())
1690 })
1691 }
1692
1693 /// [`ShutdownBlockReasonDestroy`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-shutdownblockreasondestroy)
1694 /// function.
1695 pub fn ShutdownBlockReasonDestroy(&self) -> SysResult<()> {
1696 bool_to_sysresult(unsafe { ffi::ShutdownBlockReasonDestroy(self.ptr()) })
1697 }
1698
1699 /// [`ShutdownBlockReasonQuery`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-shutdownblockreasonquery)
1700 /// function.
1701 #[must_use]
1702 pub fn ShutdownBlockReasonQuery(&self) -> SysResult<String> {
1703 let mut sz = 0u32;
1704 bool_to_sysresult(unsafe {
1705 ffi::ShutdownBlockReasonQuery(self.ptr(), std::ptr::null_mut(), &mut sz)
1706 })?;
1707
1708 let mut buf = WString::new_alloc_buf(sz as _);
1709 bool_to_sysresult(unsafe {
1710 ffi::ShutdownBlockReasonQuery(self.ptr(), buf.as_mut_ptr(), &mut sz)
1711 })
1712 .map(|_| buf.to_string())
1713 }
1714
1715 /// [`TileWindows`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-tilewindows)
1716 /// function.
1717 pub fn TileWindows(
1718 &self,
1719 how: co::MDITILE,
1720 rect: Option<RECT>,
1721 kids: &[&HWND],
1722 ) -> SysResult<u16> {
1723 match unsafe {
1724 ffi::TileWindows(
1725 self.ptr(),
1726 how.raw(),
1727 pcvoid_or_null(rect.as_ref()),
1728 kids.len() as _,
1729 vec_ptr(kids) as _,
1730 )
1731 } {
1732 0 => match GetLastError() {
1733 co::ERROR::SUCCESS => Ok(0),
1734 err => Err(err),
1735 },
1736 c => Ok(c),
1737 }
1738 }
1739
1740 /// [`TranslateAccelerator`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translateacceleratorw)
1741 /// function.
1742 pub fn TranslateAccelerator(&self, haccel_table: &HACCEL, msg: &mut MSG) -> SysResult<()> {
1743 bool_to_sysresult(unsafe {
1744 ffi::TranslateAcceleratorW(self.ptr(), haccel_table.ptr(), pvoid(msg))
1745 })
1746 }
1747
1748 /// [`UnregisterHotKey`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-unregisterhotkey)
1749 /// function.
1750 pub fn UnregisterHotKey(&self, id: i32) -> SysResult<()> {
1751 bool_to_sysresult(unsafe { ffi::UnregisterHotKey(self.ptr(), id) })
1752 }
1753
1754 /// [`UpdateLayeredWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-updatelayeredwindow)
1755 /// function.
1756 pub fn UpdateLayeredWindow(
1757 &self,
1758 hdc_dest: Option<&HDC>,
1759 pt_dest: Option<&POINT>,
1760 size: Option<&SIZE>,
1761 hdc_src: Option<&HDC>,
1762 pt_src: Option<&POINT>,
1763 key: COLORREF,
1764 blend: &BLENDFUNCTION,
1765 flags: co::ULW,
1766 ) -> SysResult<()> {
1767 bool_to_sysresult(unsafe {
1768 ffi::UpdateLayeredWindow(
1769 self.ptr(),
1770 hdc_dest.map_or(std::ptr::null_mut(), |hdc| hdc.ptr()),
1771 pcvoid_or_null(pt_dest),
1772 pcvoid_or_null(size),
1773 hdc_src.map_or(std::ptr::null_mut(), |hdc| hdc.ptr()),
1774 pcvoid_or_null(pt_src),
1775 key.raw(),
1776 pcvoid(blend),
1777 flags.raw(),
1778 )
1779 })
1780 }
1781
1782 /// [`UpdateWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-updatewindow)
1783 /// function.
1784 pub fn UpdateWindow(&self) -> SysResult<()> {
1785 bool_to_sysresult(unsafe { ffi::UpdateWindow(self.ptr()) })
1786 }
1787
1788 /// [`ValidateRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-validaterect)
1789 /// function.
1790 pub fn ValidateRect(&self, rc: Option<RECT>) -> SysResult<()> {
1791 bool_to_sysresult(unsafe { ffi::ValidateRect(self.ptr(), pcvoid_or_null(rc.as_ref())) })
1792 }
1793
1794 /// [`ValidateRgn`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-validatergn)
1795 /// function.
1796 pub fn ValidateRgn(&self, hrgn: &HRGN) -> SysResult<()> {
1797 bool_to_sysresult(unsafe { ffi::ValidateRgn(self.ptr(), hrgn.ptr()) })
1798 }
1799
1800 /// [`WindowFromPhysicalPoint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-windowfromphysicalpoint)
1801 /// function.
1802 #[must_use]
1803 pub fn WindowFromPhysicalPoint(pt: POINT) -> Option<HWND> {
1804 ptr_to_option_handle(unsafe { ffi::WindowFromPhysicalPoint(pt.x, pt.y) })
1805 }
1806
1807 /// [`WindowFromPoint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-windowfrompoint)
1808 /// function.
1809 #[must_use]
1810 pub fn WindowFromPoint(pt: POINT) -> Option<HWND> {
1811 ptr_to_option_handle(unsafe { ffi::WindowFromPoint(pt.x, pt.y) })
1812 }
1813
1814 /// [`WinHelp`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-winhelpw)
1815 /// function.
1816 pub fn WinHelp(&self, help_file: &str, cmd: co::HELPW, data: usize) -> SysResult<()> {
1817 bool_to_sysresult(unsafe {
1818 ffi::WinHelpW(self.ptr(), WString::from_str(help_file).as_ptr(), cmd.raw(), data)
1819 })
1820 }
1821}